﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DevExpress.Web.ASPxCallback;
using TireService.Data;
using DevExpress.Web.ASPxEditors;

namespace TireService.Web.View.ResourceView
{
    public partial class ServiceCarGeoAreaAllocationList : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Page.IsPostBack != true)
            {
                txtSelectedStartDate.Value = DateTime.Now;
                txtSelectedEndDate.Value = DateTime.Now.AddMonths(3);

                TireServiceDB db = new TireServiceDB();

                // Bind dropdown lists
                ddlServiceCar.DataSource = db.GetServiceCars();
                ddlServiceCar.Columns.Clear();
                ddlServiceCar.Columns.Add("ServiceCarId", "Nr");
                ddlServiceCar.Columns.Add("Description", "Beskrivelse");
                ddlServiceCar.ValueField = "ServiceCarId";
                ddlServiceCar.DropDownStyle = DropDownStyle.DropDownList;
                ddlServiceCar.IncrementalFilteringMode = IncrementalFilteringMode.StartsWith;
                ddlServiceCar.DataBind();
                ddlServiceCar.SelectedIndex = 0;

                ddlServiceGeographicalArea.DataSource = db.GetServiceGeographicalAreas();
                ddlServiceGeographicalArea.TextField = "Description";
                ddlServiceGeographicalArea.ValueField = "ServiceGeoAreaId";
                ddlServiceGeographicalArea.DataBind();
                ddlServiceGeographicalArea.SelectedIndex = 0;

                BindServiceCarGeoAreaAllocation(db, Convert.ToInt32(ddlServiceCar.SelectedItem.Value), Convert.ToDateTime(txtSelectedStartDate.Value), Convert.ToDateTime(txtSelectedEndDate.Value));
            }
        }

        /// <summary>
        /// Function - callback that runs when create new service car allocation has been selected, bind none allocated dates for selected servicecar
        /// </summary>
        protected void callbackCreateServiceCarGeoAreaAllocationPanel_Callback(object source, DevExpress.Web.ASPxClasses.CallbackEventArgsBase e)
        {
            TireServiceDB db = new TireServiceDB();

            BindServiceCarNoneGeoAreaAllocated(db, Convert.ToInt32(e.Parameter), Convert.ToDateTime(txtSelectedStartDate.Value), Convert.ToDateTime(txtSelectedEndDate.Value), Convert.ToInt32(ddlServiceGeographicalArea.Value));
        }

        /// <summary>
        /// Function that binds gridview with list on how specific service car is allocated to which geoareas in a specific timeperiod
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="ServiceCarId">Id on servicecar</param>
        /// <param name="StartDate">Startdate for period</param>
        /// <param name="EndDate">Enddate for period</param>
        private void BindServiceCarGeoAreaAllocation(TireServiceDB db, int ServiceCarId, DateTime StartDate, DateTime EndDate)
        {
            var servicecarareas = from p in db.ServiceCarGeographicalAreaAllocations
                                  join v in db.ServiceGeographicalAreas on p.ServiceGeoAreaId equals v.ServiceGeoAreaId into pv
                                  from x in pv.DefaultIfEmpty()
                                  where p.ServiceCarId == ServiceCarId & p.ScheduleDate >= StartDate & p.ScheduleDate <= EndDate & x.ServiceGeoAreaId != null
                                  select new
                                  {
                                      p.ServiceCarId,
                                      p.ScheduleDate,
                                      p.CountryId,
                                      p.ServiceGeoAreaId,
                                      p.ServiceCarAreaAllocationId,
                                      AreaDescription = x.Description
                                      //Capacity = db.GetServiceCarScheduleDetails(p.ServiceCarId, p.ScheduleDate).Count(),
                                      //AvailableCapacity = db.GetServiceCarScheduleDetails(p.ServiceCarId, p.ScheduleDate).Where(d => d.ScheduleDetailTypeId == (int)Shared.ScheduleDetailType.Available).Count()
                                  };

            gvServiceCarGeoAreaAllocation.DataSource = servicecarareas.ToList();
            gvServiceCarGeoAreaAllocation.DataBind();
        }

        /// <summary>
        /// Function that binds gridview with none allocated dates for a specific servicecar and also dates that are allocated for a specific geoarea to that servicecar
        /// </summary>
        /// <param name="db">Connection to database</param>
        /// <param name="ServiceCarId">Id on servicecar</param>
        /// <param name="StartDate">Startdate for period</param>
        /// <param name="EndDate">Enddate for period</param>
        /// <param name="ServiceGeoAreaId">Geographical area</param>
        private void BindServiceCarNoneGeoAreaAllocated(TireServiceDB db, int ServiceCarId, DateTime StartDate, DateTime EndDate, int ServiceGeoAreaId) 
        {

            var servicecarareas = from p in db.ServiceCarSchedules
                                  join y in db.ServiceCarGeographicalAreaAllocations on
                                  new { Col1 = p.ServiceCarId, Col2 = p.ScheduleDate }
                                  equals
                                  new { Col1 = y.ServiceCarId, Col2 = y.ScheduleDate }
                                  into py
                                  from z in py.DefaultIfEmpty()
                                  join v in db.ServiceGeographicalAreas on z.ServiceGeoAreaId equals v.ServiceGeoAreaId into pv
                                  from x in pv.DefaultIfEmpty()
                                  where p.ServiceCarId == ServiceCarId & p.ScheduleDate >= StartDate & p.ScheduleDate <= EndDate// & (z.ServiceGeoAreaId == 0 | z.ServiceGeoAreaId == ServiceGeoAreaId)
                                  select new
                                  {
                                      p.ServiceCarScheduleId,
                                      p.ServiceCarId,
                                      p.ScheduleDate,
                                      CountryId = (int?)z.CountryId,
                                      ServiceGeoAreaId = (int?)z.ServiceGeoAreaId,
                                      ServiceCarAreaAllocationId = (int?)z.ServiceCarAreaAllocationId,
                                      AreaDescription = x.Description,
                                      Capacity = db.ServiceCarScheduleDetails.Where(q => q.ServiceCarId == p.ServiceCarId & q.ScheduleDate == p.ScheduleDate).Count(),
                                      AvailableCapacity = db.ServiceCarScheduleDetails.Where(q => q.ServiceCarId == p.ServiceCarId & q.ScheduleDate == p.ScheduleDate & q.ScheduleDetailTypeId == (int)Shared.ScheduleDetailType.Available).Count(),
                                      AreaAllocated = (bool)(z.ServiceGeoAreaId == null ? false : true)
                                  };

            //ServiceGeoAreaId = (z.ServiceGeoAreaId == null ? 0 : z.ServiceGeoAreaId),
            //                          ServiceCarAreaAllocationId = (z.ServiceCarAreaAllocationId == null ? 0 : z.ServiceCarAreaAllocationId),
            //                          AreaDescription = x.Description ?? "",
            //                          Capacity = db.ServiceCarScheduleDetails.Where(q => q.ServiceCarId == p.ServiceCarId & q.ScheduleDate == p.ScheduleDate).Count(),
            //                          AvailableCapacity = db.ServiceCarScheduleDetails.Where(q => q.ServiceCarId == p.ServiceCarId & q.ScheduleDate == p.ScheduleDate & q.ScheduleDetailTypeId == (int)Shared.ScheduleDetailType.Available).Count()

            var servicefilter = servicecarareas.Where(p => p.ServiceGeoAreaId == null | p.ServiceGeoAreaId == ServiceGeoAreaId).OrderBy(d => d.ScheduleDate).ToList();

            gvAvailableScheduleDates.DataSource = servicefilter;
            gvAvailableScheduleDates.DataBind();
        }

        /// <summary>
        /// Postback function that updates overview of allocated geoareas for a specific servicecar
        /// </summary>
        protected void gvServiceCarGeoAreaAllocation_CustomCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomCallbackEventArgs e)
        {
            TireServiceDB db = new TireServiceDB();

            BindServiceCarGeoAreaAllocation(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(txtSelectedStartDate.Value), Convert.ToDateTime(txtSelectedEndDate.Value));
        }

        /// <summary>
        /// Postback function that updates overview of none allocated schedule dates for a specific servicecar
        /// </summary>
        protected void gvAvailableScheduleDates_CustomCallback(object sender, DevExpress.Web.ASPxGridView.ASPxGridViewCustomCallbackEventArgs e)
        {
            TireServiceDB db = new TireServiceDB();

            BindServiceCarNoneGeoAreaAllocated(db, Convert.ToInt32(ddlServiceCar.Value), Convert.ToDateTime(txtSelectedStartDate.Value), Convert.ToDateTime(txtSelectedEndDate.Value), Convert.ToInt32(ddlServiceGeographicalArea.Value));
        }

        /// <summary>
        /// Callback function that deletes geoarea allocation to servicecar
        /// </summary>
        protected void callDeleteServiceCarGeoAreaAllocation_Callback(object sender, CallbackEventArgs e)
        {
            TireServiceDB db = new TireServiceDB();

            // Get value (ServiceCarAreaAllocationId)
            int ServiceCarAreaAllocationId  = Convert.ToInt32(e.Parameter);

            // Delete servicecar geoarea allocation
            ServiceCarGeographicalAreaAllocation servicecararea = db.GetServiceCarGeographicalAreaAllocation(ServiceCarAreaAllocationId);

            if (servicecararea != null)
            {
                db.RemoveServiceCarGeographicalAreaAllocation(servicecararea);

                db.SubmitChanges();
            }
            else
            {
                // Throw error message
                throw new ArgumentException("Område allokering ikke fundet");
            }

            db.Dispose();
        }

        /// <summary>
        /// Callback function that updates geoarea allocation to servicecar
        /// </summary>
        protected void callbackUpdateServiceCarAreaAllocation_Callback(object sender, CallbackEventArgs e)
        {
            // Get values (ServiceCarScheduleId, Remove/Add area, GeographicalArea - ServiceGeoAreaId)
            string[] param = e.Parameter.Split('|');

            // Save new timeslot          
            int ServiceCarScheduleId = Convert.ToInt32(param[0]);
            bool AddArea = Convert.ToBoolean(param[1]);
            int ServiceGeoAreaId = Convert.ToInt32(param[2]);

            TireServiceDB db = new TireServiceDB();

            ServiceCarSchedule schedule = db.GetServiceCarSchedule(ServiceCarScheduleId);

            if (schedule == null)
	        {
		        // Throw error message
                throw new ArgumentException("Kørselsdag for service bil ikke fundet");
	        }

            if (AddArea)
            {
                ServiceCarGeographicalAreaAllocation servicecararea = new ServiceCarGeographicalAreaAllocation();

                servicecararea.ServiceCarId = schedule.ServiceCarId;
                servicecararea.ScheduleDate = schedule.ScheduleDate;
                servicecararea.ServiceGeoAreaId = ServiceGeoAreaId;
                servicecararea.CountryId = db.GetServiceGeographicalAreaCountryId(ServiceGeoAreaId);

                db.AddServiceCarGeographicalAreaAllocation(servicecararea);
            }
            else
            {
                // Remove
                ServiceCarGeographicalAreaAllocation servicecararea = db.GetServiceCarGeographicalAreaAllocation(schedule.ServiceCarId, schedule.ScheduleDate);

                if (servicecararea == null)
                {
                    // Throw error message
                    throw new ArgumentException("Områder allokering ikke fundet");
                }
                else
                {
                    db.RemoveServiceCarGeographicalAreaAllocation(servicecararea);
                }
            }

            db.SubmitChanges();

            db.Dispose();
        }
    }
}